package com.jkdz.spyke.widgetUIs {
	import spark.components.Button;
	import spark.components.Form;
	import spark.components.FormItem;
	import spark.components.Group;
	import spark.components.HSlider;
	import spark.components.TextArea;
	import spark.components.VideoDisplay;
	import spark.components.mediaClasses.DynamicStreamingVideoItem;
	import spark.components.mediaClasses.DynamicStreamingVideoSource;
	import spark.events.TextOperationEvent;
	import spark.filters.ColorMatrixFilter;
	import spark.layouts.HorizontalAlign;
	import spark.layouts.VerticalLayout;
	import spark.primitives.Line;

	import com.jkdz.spyke.flexUI.helpers.Link;
	import com.jkdz.spyke.flexUI.helpers.LocalPropertyListener;
	import com.jkdz.spyke.flexUI.helpers.SuperWindow;
	import com.jkdz.spyke.flexUI.main.Main;
	import com.jkdz.spyke.rs.SpykeAbstractCommunicatorListener;
	import com.jkdz.spyke.rs.SpykePhone;
	import com.jkgh.remedy.core.client.RemedyCodec;

	import org.osmf.layout.ScaleMode;
	import org.osmf.net.StreamType;

	import mx.binding.utils.BindingUtils;
	import mx.controls.Spacer;
	import mx.controls.TextInput;
	import mx.core.FlexGlobals;
	import mx.graphics.SolidColorStroke;

	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.NetStatusEvent;
	import flash.geom.Point;
	import flash.media.Microphone;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.utils.setTimeout;
	
	public class SpykePhoneUI extends SpykeWidgetUI implements SpykeAbstractCommunicatorListener, LocalPropertyListener {
		
		public static var theOwnedInstance:SpykePhone;
		
		private var widget:SpykePhone;
		private var window:SuperWindow;
		private var statusText:TextArea;
		private var closeConnections:Function;
		private var video:VideoDisplay;
		
		public function SpykePhoneUI(widget:SpykePhone) {
			this.widget = widget;
			widget.registerListener(this);
		}
		
		public function userNameChanged(name:String):void {
			if (isOwned()) {
				widget.setPersonName(name);
			}
		}
		
		override public function display(onComplete:Function):void {
			
			widget.getPersonName(function(name:String):void {
				widget.getPersonStatus(function(status:String):void {
					widget.getStreamID(function(streamID:String):void {
						showUI(name, status, streamID, onComplete);
					});
				});
			});
		}
		
		public function unPublished():void {
			if (!isOwned()) {
				if (closeConnections != null) {
					setTimeout(closeConnections, 2*SuperWindow.BOUNCE_EFFECT_DURATION);
				}
				window.close();
			}
		}
		
		public function personNameChanged(name:String):void {
			window.title = name;
		}
		
		public function personStatusChanged(status:String):void {
			if (!isOwned()) {
				statusText.text = status;
			}
		}
		
		private function showUI(name:String, status:String, streamID:String, onComplete:Function):void {
			
			if (isOwned()) {
				widget.registerOwner(this);
			}
			
			var vl:VerticalLayout = new VerticalLayout();
			vl.gap = 0;
			vl.horizontalAlign = HorizontalAlign.CENTER;
			this.layout = vl;
			
			video = new VideoDisplay();
			video.height = 0;
			video.scaleMode = ScaleMode.STRETCH;
			
			if (isOwned()) {
				publishStream(streamID);
			} else {
				var ns:DynamicStreamingVideoSource = new DynamicStreamingVideoSource();
				ns.host = Main.RTMP_LOCATION;
				ns.streamType = StreamType.LIVE;
				var item:DynamicStreamingVideoItem = new DynamicStreamingVideoItem();
				item.streamName = streamID;
				ns.streamItems = Vector.<DynamicStreamingVideoItem>([item]);
				video.source = ns;
				
				closeConnections = function():void {
					video.stop();
				};
			}
			
			this.addElement(video);
			
			var separator:Line = new Line();
			separator.stroke = new SolidColorStroke(0xff000000, 1, 1.0, false, "normal", "square");
			separator.yFrom = 0;
			separator.yTo = 0;
			separator.xFrom = 0;
			
			video.alpha = separator.alpha = 0.0;
			
			BindingUtils.bindSetter(function(v:Number):void {
				separator.xTo = v-1;
				video.alpha = separator.alpha = v > 10 ? 1.0 : 0.0;
				if (statusText) {
					statusText.alpha = video.alpha;
				}
				if (settingsLink) {
					settingsLink.alpha = video.alpha;
				}
				if (slider) {
					slider.alpha = video.alpha;
				}
			}, video, "width");
			this.addElement(separator);
			
			var highSpacer:Spacer = new Spacer();
			highSpacer.height = 10;
			this.addElement(highSpacer);
			
			statusText = new TextArea();
			statusText.selectable = true;
			statusText.editable = isOwned();
			statusText.text = status;
			statusText.height = 36;
			statusText.maxChars = 160;
			statusText.alpha = 0;
			statusText.filters = isOwned() ? [] : [new ColorMatrixFilter([
				0.8, 0, 0, 0, 0,
				0, 0.8, 0, 0, 0,
				0, 0, 0.8, 0, 0,
				0, 0, 0, 1, 0
			])];
			statusText.addEventListener(TextOperationEvent.CHANGE, function(e:Event):void {
				widget.setPersonStatus(statusText.text);
			});
			BindingUtils.bindSetter(function(v:Number):void {
				statusText.width = v-20;
			}, video, "width");
			this.addElement(statusText);
			
			var lowSpacer:Spacer = new Spacer();
			lowSpacer.height = 10;
			this.addElement(lowSpacer);
			
			if (isOwned()) {
				var settingsLink:Link = new Link("Settings");
				settingsLink.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
					showChangePersonNameDialog();	
				});
				settingsLink.toolTip = "Click here to change SpykePhone settings.";
				settingsLink.alpha = 0;
				this.addElement(settingsLink);
			} else {
				var slider:HSlider = new HSlider();
				slider.minimum = 0;
				slider.maximum = 1;
				slider.stepSize = 0.01;
				slider.value = 0.8;
				slider.alpha = 0;
				BindingUtils.bindSetter(function(v:Number):void {
					slider.width = v-20;
				}, video, "width");
				BindingUtils.bindProperty(video, "volume", slider, "value"); 
				this.addElement(slider);
			}
			
			var endSpacer:Spacer = new Spacer();
			endSpacer.height = 10;
			this.addElement(endSpacer);
			
			if (isOwned()) {
				name = (Main)(FlexGlobals.topLevelApplication).getUserName();
				widget.setPersonName(name);
			}
			
			(Main)(FlexGlobals.topLevelApplication).addLocalPropertyListener(this);
			
			this.window = SuperWindow.display(FlexGlobals.topLevelApplication as Main, this, name, false, isOwned(), true, false, new Point(120+Math.random()*((FlexGlobals.topLevelApplication as Main).width-360), 90+Math.random()*((FlexGlobals.topLevelApplication as Main).height-270)), onClose);

			video.width = 200;
			
			onComplete();
		}
		
		private function publishStream(streamID:String):void {
			var connection:NetConnection = new NetConnection();
			connection.addEventListener(NetStatusEvent.NET_STATUS, function(event:NetStatusEvent):void {
				
				if (event.info.code == "NetConnection.Connect.Success") {
					var stream:NetStream = new NetStream(connection);
					stream.attachAudio(Microphone.getMicrophone());
					stream.publish(streamID, "live");
					video.width = 200;
					closeConnections = function():void {
						stream.close();
						connection.close();
						video.stop();
					};
				}
			});
			connection.connect(Main.RTMP_LOCATION);
		}
		
		private function onClose():void {
			if (isOwned()) {
				theOwnedInstance = null;
				if (closeConnections != null) {
					closeConnections();
				}
				(Main)(FlexGlobals.topLevelApplication).removeLocalPropertyListener(this);
				widget.unPublish();
			}
		}
		
		private function showChangePersonNameDialog():void {
			
			var crfg:Group = new Group();
			var vl:VerticalLayout = new VerticalLayout();
			vl.horizontalAlign = HorizontalAlign.CENTER;
			vl.paddingBottom = 10.0;
			crfg.layout = vl;
			var crff:Form = new Form();
			var crffi:FormItem = new FormItem();
			var crfti:TextInput = new TextInput();
			var crfb:Button = new Button();
			crfb.label = "OK";
			var thisReference:SpykePhoneUI = this;
			var submit:Function = function():void {
				if (crfti.text.length == 0) {
					SuperWindow.alert(FlexGlobals.topLevelApplication as Main, "Wrong name", "Your name cannot be empty.", function():void {
						cnw.close();
					});
				} else {
					widget.setPersonName(crfti.text);
					(Main)(FlexGlobals.topLevelApplication).setUserName(crfti.text, thisReference);
					cnw.close();
				}
			};
			crfb.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void {
				submit();
			});
			crffi.label = "Your name:";
			crffi.addElement(crfti);
			crfti.text = window.title;
			crff.addElement(crffi);
			crfti.addEventListener(KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent):void {
				if (e.charCode == 13) {
					submit();
				}
			});
			crfg.addElement(crff);
			crfg.addElement(crfb);
			var cnw:SuperWindow = SuperWindow.display(FlexGlobals.topLevelApplication as Main, crfg, "SpykePhone settings", true, true, true, false);
			focusManager.setFocus(crfti);
		}
		
		private function isOwned():Boolean {
			return RemedyCodec.equalMOs(widget, theOwnedInstance);
		}
		
		public static function own(widget:SpykePhone):void {
			theOwnedInstance = widget;
		}
		
		public static function canOwn():Boolean {
			if (!Microphone.isSupported) {
				SuperWindow.alert(FlexGlobals.topLevelApplication as Main, "Error", "Microphone is not supported on your platform.");
				return false;
			}
			if (Microphone.names.length == 0) {
				SuperWindow.alert(FlexGlobals.topLevelApplication as Main, "Error", "There is no microphone.");
				return false;
			}
			if (Microphone.getMicrophone() == null) {
				SuperWindow.alert(FlexGlobals.topLevelApplication as Main, "Error", "The microphone is disabled or already in use by another application.");
				return false;
			}
			if (theOwnedInstance != null) {
				SuperWindow.alert(FlexGlobals.topLevelApplication as Main, "Error", "You cannot use more then one SpykePhone at once.");
				return false;
			}
			if (SpykeWebcamUI.theOwnedInstance != null) {
				SuperWindow.alert(FlexGlobals.topLevelApplication as Main, "Error", "You cannot use both SpykePhone and SpykeWebcam at once.");
				return false;
			}
			return true;
		}
	}		
}